using System;
using System.Collections.Generic;
using System.IO;
using Newtonsoft.Json;
using UnityEngine;

public class ErlianbanAnalysis : BatchProcessor
{
    public int checkDaysAfterRuchang = 3;
    private static string stocksErlianbanDir(int fromYear)  => StockDataAnalysis.dataOutputDir + $"Erlianban/{fromYear}_{System.DateTime.Now.Year}/";
    public static string stocksErlianbanPath(int fromYear, string stockCode) => stocksErlianbanDir(fromYear) + $"{stockCode}.json";
    public int fromYear => AppController.instance.StockDataAnalysis.fromYear;

    [ContextMenu("FindAllStocksErlianban")]
    void FindAllStocksErlianban()
    {
        m_totalGoUpRate = 0;
        m_totalFoundCount = 0;
        actionInterval = 0.01f;
        DoActionToAllStocks(DoFindstocksErlianban);
    }

    #region test
    [NonSerialized]
    private StockAllData m_stockAllData;
    StockAllData testStockData
    {
        get
        {
            if (m_stockAllData == null || m_stockAllData.stockTransitions == null)
            {
                m_stockAllData = StocksDataController.instance.GetStockAllData(testStock,fromYear);
            }
            return m_stockAllData;
        }
    }
    public string testStock = "000001";

    [ContextMenu("TestFindstocksErlianban")]
    void TestFindstocksErlianban()
    {
        var gu = FindErlianban(testStockData);
        if (gu != null && gu.transitionsRanges != null && gu.transitionsRanges.Count > 0)
        {
            var result = AnalysisErlianbanResult(gu);
            Debug.LogError($"${testStockData.stockData.dm} 的月内二连板波段有{JsonConvert.SerializeObject(gu)}, " +
                           $"入场后{checkDaysAfterRuchang}天平均上涨：{result.averGoUpRate}");
        }
        else
        {
            Debug.LogError($"${testStockData.stockData.dm} 找不到月内二连板波段");
        }
    }
    
    #endregion

    private int m_totalFoundCount;
    private int m_goUpCount;
    float m_totalGoUpRate = 0;
    private float averGoUpRate;
    void DoFindstocksErlianban(StockData stock)
    {
        var stockAllData = StocksDataController.instance.GetStockAllData(stock.dm,fromYear);
        var found = FindErlianban(stockAllData);
        if (found != null && found.transitionsRanges != null && found.transitionsRanges.Count > 0)
        {
            var result = AnalysisErlianbanResult(found);
            Debug.Log($"${stock.dm} 的月内二连板波段有{JsonConvert.SerializeObject(found)}, 入场后{checkDaysAfterRuchang}天平均上涨：{result.averGoUpRate}");
            
            string str = JsonConvert.SerializeObject(found);
            //Debug.Log(str);
            File.WriteAllText(stocksErlianbanPath(fromYear, stock.dm), str);

            m_totalGoUpRate += result.averGoUpRate;
            if (result.averGoUpRate > 0)
                m_goUpCount++;
            m_totalFoundCount++;
        }
    }
    protected override void onCompleted()
    {
        if (m_totalFoundCount > 0)
        {
            float goUpPercentage = (float) m_goUpCount / m_totalFoundCount;
            float averGoUpRate = m_totalGoUpRate / m_totalFoundCount;
            string content =
                $"{m_totalFoundCount} 个月内二连板波段,入场后{checkDaysAfterRuchang}天上涨的有{m_goUpCount}个，上涨概率为：{goUpPercentage}, 平均上涨：{averGoUpRate}";
            Debug.LogError(content);
            onEnd?.Invoke(content);
        }
        else if (m_pickedStocks != null)
        {
            string content = JsonConvert.SerializeObject(m_pickedStocks);
            Debug.LogError($"选出的疑似月内二连板波段股票有：{content}");
            onEnd?.Invoke(content);
        }
    }
    
    StockYijianfenghouRanges FindErlianban(StockAllData stock, int beginTransitionIndex = 1, bool needSanshou = true)
    {
        Debug.Log($"FindErlianban:{stock.stockData.dm}");

        if (!Directory.Exists(stocksErlianbanDir(fromYear)))
        {
            Directory.CreateDirectory(stocksErlianbanDir(fromYear));
        }

        var stockAllData = StocksDataController.instance.GetStockAllData(stock.stockData.dm, fromYear);
        if (stockAllData == null || stockAllData.stockTransitions == null)
            return null;

        var erlianban = new StockYijianfenghouRanges();
        erlianban.stockCode = stock.stockData.dm;
        erlianban.transitionsRanges = new List<YijianfenghouRange>();
        
        var transitions = stockAllData.stockTransitions;
        for (int i = beginTransitionIndex; i < transitions.Count; i++)
        {
            if (i < 2) continue;
            
            var cur = transitions[i];
            var pre = transitions[i - 1];
            var pre2 = transitions[i - 2];

            //二连板
            bool goUpTop = (cur.c - pre.c) / pre.c > 0.096f;
            bool preGoUpTop = (pre.c - pre2.c) / pre2.c > 0.096f;
            if (goUpTop && preGoUpTop)
            {
                int sanpo = 0;
                int godowncount = 0;
                //后3连跌
                for (int j = i + 1; j <= i + 4; j++)
                {
                    if (j >= transitions.Count)
                        break;

                    if (transitions[j].c < pre.c) // cur.l)
                    {
                        sanpo = j;
                        godowncount++;
                    }
                }

                if (godowncount < 2)
                {
                    return null;
                }

                //没跌破首板的一半
                bool goDownOnHalf = transitions[sanpo].c > pre.o;//(pre.c + pre.o) / 2;
                if (!goDownOnHalf)
                {
                    Debug.Log($"{stock.stockData.dm} 跌破了首板开盘价");
                    return null;
                }

                if (needSanshou)
                    Debug.Log($"找到一个月内二连板关注点：{JsonConvert.SerializeObject(transitions[sanpo])}");
                else
                    Debug.Log($"找到一个月内二连板雏形：{transitions[i]}");

                var erlianbanRange = new YijianfenghouRange();
                var range = new List<TransitionData>();
                for (int k = i - 5; k <= i + 10; k++)
                {
                    if (k < 0 || k >= transitions.Count)
                        break;

                    range.Add(transitions[k]);
                }

                if (needSanshou)
                    erlianbanRange.ruChangIndex = range.IndexOf(transitions[sanpo]);
                erlianbanRange.goUpTopIndex = range.IndexOf(transitions[i]);
                erlianbanRange.posanIndex = range.IndexOf(transitions[sanpo]);
                erlianbanRange.transitions = range;
                erlianban.transitionsRanges.Add(erlianbanRange);
            }
        }
        return erlianban;
    }

    YijianfenghouResult AnalysisErlianbanResult(StockYijianfenghouRanges ranges)
    {
        YijianfenghouResult result = new YijianfenghouResult();
        if (ranges.transitionsRanges != null && ranges.transitionsRanges.Count > 0)
        {
            double total = 0;
            foreach (var Range in ranges.transitionsRanges)
            {
                if (Range.ruChangIndex > 0 &&
                    Range.ruChangIndex < Range.transitions.Count)
                {
                    var ruchangDian = Range.transitions[Range.ruChangIndex];
                    int endIndex = Range.ruChangIndex + checkDaysAfterRuchang;
                    if (endIndex >= Range.transitions.Count)
                        endIndex = Range.transitions.Count - 1;
                    double goUpRate = Range.transitions[endIndex].c - ruchangDian.c;
                    total += goUpRate;
                }
            }

            result.averGoUpRate = (float) total / ranges.transitionsRanges.Count;
        }
        return result;
    }

    

    [ContextMenu("选最近月内二连板潜在股")]
    public void PickAllErlianban()
    {
        actionInterval = 0.01f;
        m_pickedStocks = new List<StockData>();
        DoActionToAllStocks(DoPickErlianban);
    }

    private List<StockData> m_pickedStocks;
    void DoPickErlianban(StockData stock)
    {
        var stockAllData = StocksDataController.instance.GetStockAllData(stock.dm,fromYear);
        if (stockAllData == null || stockAllData.stockTransitions == null)
            return;
        
        var gu = FindErlianban(stockAllData,stockAllData.stockTransitions.Count - 15,true);
        if (gu != null && gu.transitionsRanges != null && gu.transitionsRanges.Count > 0)
        {
            if (gu.transitionsRanges != null && gu.transitionsRanges.Count > 0)
            {
                Debug.LogError($"选出月内二连板：{stock.dm} ，波段：{JsonConvert.SerializeObject(gu)}");
                m_pickedStocks.Add(stock);
            }
        }
    }
}